package com.zfsoft.deployui.controller.deploy;
import com.zfsoft.deployui.deploy.*;
import com.zfsoft.deployui.deploy.ResultInfo;
import com.zfsoft.deployui.enums.ResponseCodeEnum;
import com.zfsoft.deployui.service.AddChannelServiceImpl;
import com.zfsoft.deployui.service.AddHostServiceImpl;
import com.zfsoft.deployui.service.AddOrgServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.util.*;
import org.yaml.snakeyaml.Yaml;

@Slf4j
@RestController
@Component
@PropertySource("classpath:application.properties")
@RequestMapping("/deploy")
public class Generate {
    @Autowired
    private AddHostServiceImpl addHostService;
    @Autowired
    private AddOrgServiceImpl addOrgService;
    @Autowired
    private AddChannelServiceImpl addChannelService;

    @Value("${script.deploypath}")
    private String deployPath;
    @Value("${script.configfilepath}")
    private String configfilepath;
    @Value("${script.genfilepath}")
    private String genfilepath;
    @Value("${script.address}")
    private String address;

    List<Host> chooseHost=new ArrayList<>();
    String chooseHosts = null;
    Map<String, Object> tmpMark_ = new LinkedHashMap<>();
    Map<String, Object> tmpOrg_ = new LinkedHashMap<>();
    Map<String, Object> tmpChannel_ = new LinkedHashMap<>();
    Map<String, Object> tmpPeer_ = new LinkedHashMap<>();
    Map<String, Object> orgPeerExtend_ = new LinkedHashMap<>();
    List<String> chooseOldOrg=new ArrayList<>();
    @RequestMapping("/generate")
    @ResponseBody
    public String GenConfig(@RequestBody  String  version) throws FileNotFoundException {
        Generate configs = new Generate();
        String result = null;
        YamlUtils ss=new YamlUtils();
        try{
            File file = new File(configfilepath+"deployment.yaml");
            if(file.exists()) {
                file.delete();
            }
        }catch (Exception e){
            return e.getMessage();
        }
        try {
            // 增加生成文件路径
            result = ss.addProperty("configOutPath", genfilepath, new FileInputStream(configfilepath + "templates.yaml"));
            configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
            // 1添加/修改主机列表
            List<Host> tmpHost = addHostService.queryAll();
            Map<String, Object> tmpMark = new LinkedHashMap<>();
            for (int i = 0; i < tmpHost.size(); i++) {
                Map<String, Object> tmpAA = new LinkedHashMap<>();
                tmpAA.put("ip", tmpHost.get(i).getIp());
                tmpAA.put("user", tmpHost.get(i).getName());
                tmpAA.put("password", tmpHost.get(i).getPassword());
                tmpMark.put(tmpHost.get(i).getMark(), tmpAA);
                Host host_tmp=new Host();
                host_tmp.setMark(tmpHost.get(i).getMark());
                host_tmp.setIp(tmpHost.get(i).getIp());
                host_tmp.setName(tmpHost.get(i).getName());
                host_tmp.setPassword(tmpHost.get(i).getPassword());
                host_tmp.setStatus("1");
                addHostService.alterHost(host_tmp);
                result = ss.addProperty("hosts.pool", tmpMark, new FileInputStream(configfilepath + "deployment.yaml"));
            }
            configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
            // 2添加/修改组织列表
            List<Org1> tmpOrg = addOrgService.queryAllOrg();
            for (int i = 0; i < tmpOrg.size(); i++) {
                if (tmpOrg.get(i).getType().equals("orderer")) {
                    Map<String, Object> tmpBB = new LinkedHashMap<>();
                    tmpBB.put("name", "orderer");
                    tmpBB.put("domain", tmpOrg.get(i).getDomain());
                    tmpBB.put("orderers", tmpOrg.get(i).getHosts().split(","));
                    result = ss.addProperty("fabric.ordererOrg", tmpBB, new FileInputStream(configfilepath + "deployment.yaml"));
                    configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
                } else {
                    Map<String, Object> tmpCC = new LinkedHashMap<>();
                    tmpCC.put("usersCount", 1);
                    tmpCC.put("peers", tmpOrg.get(i).getHosts().split(","));
                    result = ss.addProperty("fabric.peerOrgs." + tmpOrg.get(i).getName(), tmpCC, new FileInputStream(configfilepath + "deployment.yaml"));
                    configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
                }
            }
            result = ss.addProperty("fabric.version" , version.replace("\"", ""), new FileInputStream(configfilepath + "deployment.yaml"));
            configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
            //3 添加/修改通道配置
            List<Channel1> tmpChannel = addChannelService.queryAllChannel();
            for (int i = 0; i < tmpChannel.size(); i++) {
                Map<String, Object> tmpDD = new LinkedHashMap<>();
                tmpDD.put("profile", "ZFConsortiumChannel");
                tmpDD.put("consortium", "ZFConsortium");
                tmpDD.put("orgs", tmpChannel.get(i).getOrgs().split(","));
                result = ss.addProperty("fabric.channels." + tmpChannel.get(i).getName(), tmpDD, new FileInputStream(configfilepath + "deployment.yaml"));
                configs.WriteStringToFile(configfilepath + "deployment.yaml", result);
            }
            return result;
        }catch (Exception e){
            return e.getMessage();
        }
    }

    public void WriteStringToFile(String filePath,String str) {
        try {
            FileOutputStream fos = new FileOutputStream(filePath);
            fos.write(str.getBytes());
            fos.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static Map<String, Object> getYamlToMap(String fileName) {
        LinkedHashMap<String, Object> yamls = new LinkedHashMap<>();
        Yaml yaml = new Yaml();
        try {
            InputStream inputStream = new FileInputStream(fileName);
            yamls = yaml.loadAs(inputStream, LinkedHashMap.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return yamls;
    }

    @RequestMapping("/deployFabric")
    @ResponseBody
    public ResultInfo DeployFabric(@RequestBody String str){
        try {
            String exe = "python";
            String[] cmdArr;
            if (str.equals("deploy")){
                 cmdArr = new String[] { exe, deployPath,"--install","--virtual-host"};
            }else if (str.equals("clean")){
                 cmdArr = new String[] { exe, deployPath,"--clean-all"};
            }else {
                return new ResultInfo(ResponseCodeEnum.FAILURE, "请选择正确的方法");
            }
            System.out.println("当前执行的命令:"+Arrays.toString(cmdArr));
            Process process = Runtime.getRuntime().exec(cmdArr);
            WebSocketServer tmpSocket=new WebSocketServer();
            ResultInfo resultStr=new ResultInfo(ResponseCodeEnum.SUCCESS, "操作成功");
            Thread shutdownThread = new Thread() {
                public void run() {
                    resultStr.setCode(ResponseCodeEnum.FAILURE.getCode());
                    resultStr.setData("部署中断,请清理网络后重新部署");
                    tmpSocket.onClose();
                    process.destroy();
                }
            };
            Runtime.getRuntime().addShutdownHook(shutdownThread);
            new Thread() {
                public void run() {
                    BufferedReader br = new BufferedReader(new
                            InputStreamReader(process.getInputStream()));
                    try {
                        String line;
                        while ((line = br.readLine()) != null) {
                            if(line!=null) {
                                if (line.equals("请不要重复部署")) {
                                    resultStr.setCode(ResponseCodeEnum.FAILURE.getCode());
                                    resultStr.setData("请不要重复部署");
                                    break;
                                }
                                tmpSocket.sendToUser(line, "234");
                                sleep(1);
                            }
                        }
                    } catch (IOException | InterruptedException e) {
                        resultStr.setCode(ResponseCodeEnum.FAILURE.getCode());
                        resultStr.setData("部署中断");
                        e.printStackTrace();
                    } finally {
                        try {
                            br.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            int res=process.waitFor();
            process.destroy();
            if (res == 0) {
                return resultStr;
            }else {
                return new ResultInfo(ResponseCodeEnum.FAILURE, "操作过程出现问题，请重新尝试操作");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultInfo(ResponseCodeEnum.FAILURE, e.getMessage());
        }
    }

    @RequestMapping(value = "/chooseHost",method = RequestMethod.POST)
    public List<Host> chooseHost(@RequestBody  Host host) {
        Host host_find = addHostService.findHost(host.getIp());
        try {
            Map<String, Object> tmpAA = new LinkedHashMap<>();
            tmpAA.put("ip", host.getIp());
            tmpAA.put("user", host.getName());
            tmpAA.put("password", host_find.getPassword());
            tmpMark_.put(host.getMark(), tmpAA);

            host.setPassword(host_find.getPassword());
            host.setStatus("1");
            addHostService.alterHost(host);
        } catch (Exception e) {
            System.out.println("失败");
        }
        return addHostService.queryByStatus("0");
    }


    @RequestMapping(value = "/chooseNewOrg",method = RequestMethod.POST)
    public List<Org1> chooseNewOrg(@RequestBody  Org1 org) {
        Map<String, Object> tmpCC = new LinkedHashMap<>();
        tmpCC.put("usersCount", 1);
        tmpCC.put("peers", org.getHosts().split(","));
        tmpOrg_.put(org.getName(), tmpCC);
        org.setStatus("1");
        addOrgService.alterOrg(org);
        return addOrgService.queryByStatus("0");
    }
    @RequestMapping(value = "/chooseOldOrg",method = RequestMethod.POST)
    public List<Host> chooseOldOrg(@RequestBody  Org1 org) {
        chooseOldOrg.add(org.getName());
        System.out.println("chooseOldOrg 执行！！"+org.getHosts());
        Map<String, Object> tmpCC = new LinkedHashMap<>();
        String[] list_host = org.getHosts().split(",");

        System.out.println("chooseOldOrg 执行！！"+list_host[0]);
        System.out.println("chooseOldOrg 执行！！!!"+addHostService.findHost_(list_host[0]));
        return addHostService.findHost_(list_host[0]);
    }


    @RequestMapping(value = "/chooseNewCha",method = RequestMethod.POST)
    public List<Channel1> chooseNewCha(@RequestBody Channel1 channel){
        System.out.println("chooseNewCha"+channel.toString());
        Map<String, Object> tmpDD = new LinkedHashMap<>();
        int tmp_size = tmpChannel_.size();
        tmpDD.put("profile", "ZFConsortiumChannel"+String.valueOf(tmp_size+1));
        tmpDD.put("consortium", "ZFConsortium"+String.valueOf(tmp_size+1));
        tmpDD.put("orgs", channel.getOrgs().split(","));
        tmpChannel_.put(channel.getName(),tmpDD);
        System.out.println("tmpChannel_::::::::::"+channel.getOrgs().split(","));
        System.out.println("tmpChannel_::::::::::"+tmpChannel_);
        channel.setStatus("1");
        addChannelService.alterChannel(channel);
        return addChannelService.queryByStatus("0");
    }


    @RequestMapping(value = "/chooseOrgHost",method = RequestMethod.POST)
    public String chooseOrgHost(@RequestBody  Host host) {
        String oldorgname = chooseOldOrg.get(chooseOldOrg.size()-1);
        Org1 org=addOrgService.findOrg(oldorgname);
        Org1 orgtmp=new Org1();
        orgtmp.setName(org.getName());
        orgtmp.setDomain(org.getDomain());
        orgtmp.setType(org.getType());
        orgtmp.setHosts(org.getHosts()+","+host.getMark());
        orgtmp.setStatus(org.getStatus());
        System.out.println("orgtmp::"+orgtmp);
        if(orgPeerExtend_.containsKey(org.getName())){
            orgPeerExtend_.put(org.getName(),orgPeerExtend_.get(org.getName())+","+host.getMark().split(","));
        }
        else{
            orgPeerExtend_.put(org.getName(),(host.getMark()+",").split(","));
        }
        tmpPeer_.put(org.getName(),orgPeerExtend_.get(org.getName()));
        System.out.println("tmpPeer_:::::::::"+orgPeerExtend_.get(org.getName()));
        System.out.println("tmpPeer_:::::::::"+tmpPeer_);
        addOrgService.alterOrg(orgtmp);
        return host.getMark();
    }

    @RequestMapping("/generate_extend")
    @ResponseBody
    public String GenExtendConfig() throws FileNotFoundException {
        Generate configs = new Generate();
        String result = null;
        YamlUtils ss=new YamlUtils();
        String version="1";
        try{
            File file = new File(configfilepath+"extend.yaml");
            if(file.exists()) {
                Yaml yaml = new Yaml();
                InputStream inputStream = new FileInputStream(configfilepath + "extend.yaml");
                final Object loadObj = yaml.load(inputStream);
                if (loadObj instanceof String) {
                    throw new IllegalArgumentException("yaml文件格式 有问题，请检查");
                }
                Map<String, Object> map = (Map<String, Object>) loadObj;
                version = String.valueOf(Integer.parseInt(map.get("version").toString())+1);
                file.delete();
            }
            else{
                version="1";
            }
        }catch (Exception e){
            return e.getMessage();
        }

        try {
            // 增加生成文件路径
            result = ss.addProperty("version", version, new FileInputStream(configfilepath + "extendtemplate.yaml"));
            System.out.println("result:::::"+result);
            configs.WriteStringToFile(configfilepath + "extend.yaml", result);
            // 添加/修改主机列表
            result = ss.addProperty("hosts.pool", tmpMark_, new FileInputStream(configfilepath + "extend.yaml"));
            configs.WriteStringToFile(configfilepath + "extend.yaml", result);

            result = ss.addProperty("AddOrgs", tmpOrg_, new FileInputStream(configfilepath + "extend.yaml"));
            configs.WriteStringToFile(configfilepath + "extend.yaml", result);
            System.out.println("tmpChannel_::"+tmpChannel_);
            result = ss.addProperty("AddChannels", tmpChannel_, new FileInputStream(configfilepath + "extend.yaml"));
            configs.WriteStringToFile(configfilepath + "extend.yaml", result);
            System.out.println("tmpPeer_::"+tmpPeer_);
            result = ss.addProperty("AddPeers", tmpPeer_, new FileInputStream(configfilepath + "extend.yaml"));
            configs.WriteStringToFile(configfilepath + "extend.yaml", result);
            return result;
        }catch (Exception e){
            return e.getMessage();
        }
    }
}
